/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	bar_scan.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-05-24
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "CR100_scan.h"



/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/

static void cr100_recv_callback(void* arg,uint8_t *buff,uint16_t size);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/

__attribute__((section(".RAM_D2"))) static cr100_t m_cr100;

/*用 str[] = {"bla"}; 生成的数组最后会加一个 0x00 导致sizeof(str)大了一 取长度该用strlen*/

static char cr100_init_buff[]={"\x02V\r\n"};//询问版本&取消持续扫码模式\x02PT03203400\r\n

static char cr100_version_rtn[]={"\x02\x43R100       V  1.02  24.04.2018\r\n"}; // 后面时版本和日期 CR100       V  1.02  24.04.2018

static char cr100_start_single[]={"\x02+\r\n"};//无回复

static char cr100_stop_single[]={"\x02-\r\n"};//处于单次扫码未完成会回复“？”

static char cr100_stop_single_rtn[]={"\x02?\r\n"};
/*CR100可以从单次扫码直接发送持续扫码命令转成持续扫码 但是持续扫码不能转成单次扫码*/
static char cr100_start_continuous[]={"\x02PT03203401\r\n"};

static char cr100_stop_continuous[]={"\x02PT03203400\r\n"};

static char cr100_reset[]={"\x02PC20\r\n"};

static char cr100_continuous_rtn[]={"\x02PS0\r\n"};

static char cr100_start_rtn[]={"\x02S\r\n"};
/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/
cr100_t* cr100_init(cr100_scan_rlt_callback pfn_cb)
{
	m_cr100.status=CR100_UNINIT;
	m_cr100.pfn_scan_rlt_cb =pfn_cb;
	m_cr100.ack_cnt=0;
	
	m_cr100.p_uart=bsp_uart_init(BARCODE_CR100_UART_CHN,CR100_UART_BAUDRATE);
	
	bsp_uart_tx_dma_init(m_cr100.p_uart,NULL);
	bsp_uart_rx_dma_init(m_cr100.p_uart,cr100_recv_callback,m_cr100.rx_buff,CR100_UART_RXBUFF_SIZE);

	bsp_uart_dma_transfer(m_cr100.p_uart,cr100_init_buff,strlen(cr100_init_buff));
	m_cr100.ack_cnt=1;
	
	return &m_cr100;
}
cr100_status_t cr100_start(cr100_status_t new_status)
{
	memset(m_cr100.rx_buff,0,CR100_UART_RXBUFF_SIZE);
	if(m_cr100.status == CR100_UNINIT || m_cr100.ack_cnt!=0)
	{
		Trace_Log("CR100 scanner uninit!\r\n");
		bsp_uart_dma_transfer(m_cr100.p_uart,cr100_init_buff,strlen(cr100_init_buff));
		m_cr100.ack_cnt=1;
		tcp_err_push(ELEC_ERR_SCAN,"Scanner failed;\n");
		return CR100_ERR;
	}
	switch(new_status){
		case CR100_SINGLE_SCAN:
			bsp_uart_dma_transfer(m_cr100.p_uart,cr100_start_single,strlen(cr100_start_single));
			m_cr100.status=new_status;
//			m_cr100.ack_cnt++;
			break;
		case CR100_CONTINUOUS_SCAN:
			bsp_uart_dma_transfer(m_cr100.p_uart,cr100_start_continuous,strlen(cr100_start_continuous));
			m_cr100.status=new_status;
//			m_cr100.ack_cnt++;
			break;
		case CR100_IDLE:
			if(m_cr100.status==CR100_SINGLE_SCAN)
			{
				bsp_uart_dma_transfer(m_cr100.p_uart,cr100_stop_single,strlen(cr100_stop_single));
//				m_cr100.ack_cnt++;
			}
			else if(m_cr100.status==CR100_CONTINUOUS_SCAN)
			{
				bsp_uart_dma_transfer(m_cr100.p_uart,cr100_stop_continuous,strlen(cr100_stop_continuous));
//				m_cr100.ack_cnt++;
			}
			m_cr100.status=new_status;
			break;
		default:break;
	}
	return m_cr100.status;
}

static void cr100_recv_callback(void* arg,uint8_t *buff,uint16_t size)
{
	SCB_InvalidateDCache_by_Addr((uint32_t *)buff,size);
	
	uint8_t *p_rtn=buff;
	uint16_t remain=size;
	
	while(p_rtn-buff < size)
	{
		if(m_cr100.status ==CR100_UNINIT)
		{
			if(remain >= strlen(cr100_version_rtn) && memcmp(buff,cr100_version_rtn,CR100_VERSION_CHECK_SIZE) == 0)
			{
				if(m_cr100.ack_cnt) m_cr100.ack_cnt--;
				m_cr100.status = CR100_IDLE;
				p_rtn+=strlen(cr100_version_rtn);
				Trace_Log("CR100 scanner init success!\r\n");
				continue;
			}
			else
			{
				Trace_Log("CR100 scanner uninit!\r\n");
				return;
			}
		}
		
		remain=buff+size-p_rtn;
		if(/*m_cr100.ack_cnt && */remain >= strlen(cr100_continuous_rtn) && memcmp(buff,cr100_continuous_rtn,strlen(cr100_continuous_rtn)) == 0)
		{
			if(m_cr100.ack_cnt) m_cr100.ack_cnt--;
			p_rtn+=sizeof(cr100_continuous_rtn);
			continue;
		}
		if(/*m_cr100.ack_cnt && */ remain >= strlen(cr100_stop_single_rtn) &&memcmp(buff,cr100_stop_single_rtn,strlen(cr100_stop_single_rtn)) == 0)
		{
			if(m_cr100.ack_cnt) m_cr100.ack_cnt--;
			p_rtn+=sizeof(cr100_stop_single_rtn);
			continue;
		}
		
//		if(m_cr100.ack_cnt)
//			Trace_Log("CR100 ack receive check err!\r\n");
		
		if(*p_rtn == CR100_CMD_SEPATATOR)
		{
			uint16_t i=0;
			for(;i<remain;i++)
			{
				if(p_rtn[i] == CR100_CMD_TAIL)
					break;
			}
			if(i == remain)
			{
				Trace_Log("CR100 CMD can't find tail!\r\n");
				return;
			}
			
			if(m_cr100.pfn_scan_rlt_cb != NULL)
				m_cr100.pfn_scan_rlt_cb(&m_cr100,(p_rtn+1),i-2);
			
			if(m_cr100.status == CR100_SINGLE_SCAN)
				m_cr100.status=CR100_IDLE;
			p_rtn+=(i+1);
			continue;
		}
		
		p_rtn++;
		continue;
	}
}
cr100_status_t cr100_status(void)
{
	return m_cr100.status;
}